home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d3 / ddjhptxt.arc / GESSNER.LST < prev    next >
File List  |  1990-06-05  |  30KB  |  554 lines

  1. LISTING ONE
  2.  
  3.  
  4.   1|  {$V-} {$F+} {$O+}   { Written By:  Rick Gessner, 1989. }
  5.   2|
  6.   3|  Unit HyprText;
  7.   4|  {-------} Interface {-----------------------------------------------}
  8.   5|
  9.   6|  PROCEDURE Help_Editor(FileName: String);
  10.   7|  PROCEDURE Do_help(FileName: String; GoPage,HomePage: Word);
  11.   8|  {-------} Implementation {------------------------------------------}
  12.   9|  Uses Crt;
  13.  10|
  14.  11|  CONST HelpColor        : Array[False..true] of Byte =
  15.  12|                              ( Black*16+White,     { for normal text}
  16.  13|                                Magenta*16+Yellow); { for hot-link text.}
  17.  14|        NormalColor      : Byte = Black*16+White;   { draw screen info.}
  18.  15|        BoldColor        : Byte = White*16+Black-Blink; { for select bar.}
  19.  16|        Header           : String[50] = ' HyperText System [1.0] ';
  20.  17|        MaxLinesPerPage  = 15;
  21.  18|        MaxLineWidth     = 57;
  22.  19|
  23.  20|        PGUP    = 'I';      PGDN    = 'Q';      UpArrow = 'H'; {Edit keys}
  24.  21|        DnArrow = 'P';      LArrow  = 'K';      RArrow  = 'M';
  25.  22|        ESC     = #27;      HomeKey = 'G';      EndKey  = 'O';
  26.  23|        RETURN  = ^M;       BkSpc   = #8;       NULL    = #0;
  27.  24|        Tab     = #9;       F2      = '<';      DelKey  = 'S';
  28.  25|  Type  HelpRecord = Record  {The main structure for our hypertext files}
  29.  26|            HelpLines : Array[1..MaxLinesPerPage] of String[100];
  30.  27|      end; {String length MUST be > than MaxLineWidth to store hot-links!}
  31.  28|  Var   HelpRec    : HelpRecord;
  32.  29|        HelpFile   : File of HelpRecord;
  33.  30|        Alt,Ctrl,CommandKey : Boolean;
  34.  31| {--------------------------------------------------------------------}
  35.  32|  FUNCTION Make_String(Ch   : Char; Size : Integer) : String;
  36.  33|  Var S: string;
  37.  34|  Begin
  38.  35|      S[0] := Chr(Size);            { Set length byte = SIZE.          }
  39.  36|      FillChar(S[1],Size,Ch);       { Fill the string with chr(CH).    }
  40.  37|      Make_String:= S;              { and return the string as function}
  41.  38|  end; {Make String }               { value.                           }
  42.  39| {--------------------------------------------------------------------}
  43.  40|  PROCEDURE Draw_Box(topx,topy,botx,boty: Byte; Color,Width: byte);
  44.  41|  Type BoxPos = (TopL,TopR,BotL,BotR,Top,Bot,LSide,RSide);
  45.  42|  Var Y       : Integer;
  46.  43|  Const  Boxchar : Array[1..2,TopL..RSide] of char =
  47.  44|     (( 'Z','?','@','Y','D','D','3','3'),  {ASCII chars, single line box }
  48.  45|      ( 'I',';','H','<','M','M',':',':')); {ASCII chars, double line box }
  49.  46|  Begin
  50.  47|    TextAttr:=Color;
  51.  48|    If Not (Width in [1,2]) then Width:=1; { Sure width value is OK? }
  52.  49|    Gotoxy(TopX,TopY);    { First, draw the top line of the box...}
  53.  50|    Write( BoxChar[Width,TopL]+Make_String(BoxChar[width,top],
  54.  51|                                        BotX-TopX-1)+BoxChar[Width,TopR]);
  55.  52|    For Y:=TopY+1 to BotY-1 do
  56.  53|    Begin                 { Second, draw the middle lines of the box...}
  57.  54|            Gotoxy(TopX,Y);
  58.  55|            Write( BoxChar[Width,LSide],BoxChar[Width,RSide]:BotX-TopX);
  59.  56|    end;
  60.  57|    GotoXY(TopX,BotY);    { Third, draw the bottom line of the box. }
  61.  58|   Write( BoxChar[Width,BotL]+Make_String(BoxChar[width,top],BotX-TopX-1)+
  62.  59|                                                      BoxChar[Width,BotR])
  63.  60|  end; {Draw Box}
  64.  61| {--------------------------------------------------------------------}
  65.  62|  FUNCTION Read_KeyBoard: Char;   {Routine to get keystrokes from user}
  66.  63|  Const  CtrlMask  = $04;
  67.  64|         AltMask   = $08;
  68.  65|  Var    KBDFlag   : Byte Absolute $0040:$0017;
  69.  66|  Begin
  70.  67|   Read_KeyBoard:=ReadKey;
  71.  68|   CommandKey :=((KBDFlag AND AltMask)<>0) or ((KBDFlag AND CtrlMask)<>0);
  72.  69|   ALT  :=(KBDFlag AND AltMask)<>0; CTRL := (KBDFlag AND CtrlMask)<>0;
  73.  70|   If KeyPressed Then
  74.  71|   Begin
  75.  72|        Read_Keyboard := ReadKey; {Just in case user pressed modified key}
  76.  73|           CommandKey := True;
  77.  74|    end;
  78.  75|  end; {Read_Keyboard}
  79.  76| {--------------------------------------------------------------------}
  80.  77| PROCEDURE Show_HelpLine(X,Y,StartBold,EndBold: Integer; Var Line: String);
  81.  78|   Var I,J: Integer;
  82.  79|        PROCEDURE Write_Char(Ch: Char);
  83.  80|        Begin
  84.  81|             If Ord(Ch)>127 then Ch:=Chr(Ord(Ch)-128); {Clear high bit}
  85.  82|             If Ord(Ch)>27 then Write(Ch) else Inc(i);
  86.  83|        end;
  87.  84|   Begin
  88.  85|        TextAttr:=HelpColor[False];
  89.  86|        Window(X,Y,59,Y); ClrEOL; Window(1,1,80,25); {Prepare for output}
  90.  87|        Gotoxy(X,Y); I:=1;
  91.  88|        While I<=Length(Line) do                {Do each char in line}
  92.  89|        Begin
  93.  90|             TextAttr:=HelpColor[Ord(Line[i])>128];    {Set proper color}
  94.  91|             If I in [StartBold..EndBold] then TextAttr:=BoldColor;
  95.  92|             Write_Char(Line[i]);
  96.  93|             Inc(i);
  97.  94|        end;
  98.  95|   end; {Show helpline}
  99.  96|  {-------------------------------------------------------------------}
  100.  97|   PROCEDURE Show_Help_Page(X,Y: Integer; Var HelpRec: HelpRecord);
  101.  98|   Var I: Integer;
  102.  99|   Begin
  103. 100|      Window(X+1,Y+1,X+56,Y+MaxLinesPerPage+1); ClrScr; Window(1,1,80,25);
  104. 101|      For I:=1 to MaxLinesPerPage do
  105. 102|           Show_HelpLine(X,Y+I,0,0,HelpRec.HelpLines[I]);
  106. 103|   end; {Show help page}
  107. 104|  {-------------------------------------------------------------------}
  108. 105|   FUNCTION Determine_Actual_Line_Pos(Var Line: String; LinePos:
  109. 106|                                                       Integer): Integer;
  110. 107|   Var I,J: Integer;  {Convert visual edit column to char. position,}
  111. 108|   Begin              {by skipping over embedded hot links.}
  112. 109|        I:=0; J:=1;
  113. 110|        While (J<=Length(Line)) and (I<>LinePos) do
  114. 111|        Begin
  115. 113|                Inc(i) else Inc(j,2);
  116. 113|             Inc(j);
  117. 114|        end;
  118. 115|        Determine_Actual_Line_Pos:=J;
  119. 116|   end; {Determine actual line pos}
  120. 117|
  121. 118|  {-------------------------------------------------------------------}
  122. 119|   FUNCTION Link_Count(Var Line: String): Integer;
  123. 120|   Var I,Count: Integer;  { Returns 2*#nulls in line, used to convert }
  124. 121|   Begin                  { from actual byte pos. to visual byte pos., }
  125. 122|        Count:=0;         { during data input. }
  126. 123|        For I:=1 to Length(Line) do
  127. 124|            If Line[i]=Null then Inc(Count,2);
  128. 125|        Link_Count:=Count;
  129. 126|   end; {Link count}
  130. 127|  {-------------------------------------------------------------------}
  131. 128|   FUNCTION Input_HelpPage(X,Y: Byte; Var AHelpRec: HelpRecord): Char;
  132. 129|   Var   Ch          : Char;   { Main editing routine in this system.  }
  133. 130|         PageNum     : Byte;   { It is really just a page-oriented line }
  134. 131|         I,J,                  { editor knows how to jump over 2-byte }
  135. 132|         LinePos,              { hot-links. }
  136. 133|         RealLinePos,          { If you add editing options, take }
  137. 134|         LineNum     : Integer;{ the embedded hot-links into account! }
  138. 135|
  139. 136|         PROCEDURE Delete_Linked_Char(Var Line: String; LinePos: Integer);
  140. 137|         Var I,J: Integer;
  141. 138|         Begin
  142. 139|             LinePos:=Pred(Determine_Actual_Line_Pos(Line,LinePos));
  143. 140|             f Ord(Line[LinePos])>127 then  {Were on a linked item}
  144. 141|             egin
  145. 142|             I:=LinePos;
  146. 143|             While ((Ord(Line[I-1])>127) and (I>1)) do Dec(i);
  147. 144|             J:=LinePos;                     {Next find end of link}
  148. 145|              While ((Ord(Line[J+1])>127) and (I<Length(Line))) do Inc(J);
  149. 146|                 Delete(Line,LinePos, {Delete all of item + link if necc.}
  150. 147|                          1+(2*Ord(J=I)));
  151. 148|             end;
  152. 149|         end; {Delete linked char}
  153. 150|   Begin
  154. 151|        Show_Help_Page(X,Y,AHelpRec);  {Display this page }
  155. 152|        LinePos:=1; RealLinePos:=1;    {Now do a little init stuff.}
  156. 153|        LineNum:=1;
  157. 154|        With AHelpRec do               {Now enter main edit loop...}
  158. 155|        Repeat
  159. 156|              Show_HelpLine(X,Y+LineNum,0,0,HelpLines[LineNum]);
  160. 157|              Gotoxy(X+LinePos-1,Y+LineNum);
  161. 158|              Repeat Ch:=Read_KeyBoard Until Ch <> Null;
  162. 159|              If CommandKey then
  163. 160|                 Case Ch of
  164. 161|                  ^Y     : If RealLinePos<=Length(HelpLines[LineNum]) then
  165. 162|                          Begin    { ^Y = Delete to end of line. }
  166. 163|                            If (RealLinePos=1) then HelpLines[LineNum]:=''
  167. 164|                            else
  168. 165|                            Begin
  169. 166|                              While HelpLines[LineNum,RealLinePos]<>Null do
  170. 167|                              Delete(HelpLines[LineNum],RealLinePos,1);
  171. 168|                             If HelpLines[LineNum,RealLinePos]=Null then
  172. 169|                              Delete(HelpLines[LineNum],RealLinePos+2,255)
  173. 170|                               end
  174. 171|                          end;
  175. 172|                  F2     : Begin { F2 = Add/Remove hot-link.}
  176. 173|                            J:=RealLinePos;
  177. 174|                            While (j>0) and (HelpLines[LineNum,j]<>' ')
  178. 175|                                                                do Dec(j);
  179. 176|                            Inc(j);
  180. 177|                            If Ord(HelpLines[Linenum,j]) in [28..127] then
  181. 178|                            Repeat {Now get a valid page # to jump to...}
  182. 179|                                      Gotoxy(3,24); Write('Link Page: ');
  183. 180|                                      Readln(PageNum);
  184. 181|                                      Gotoxy(3,24); ClrEOL;
  185. 182|                                 Until (PageNum>0) and (PageNum<256);
  186. 183|                                 While (HelpLines[LineNum,j]<>' ') and
  187. 184|                                       (j<=Length(HelpLines[LineNum])) and
  188. 185|                                     (HelpLines[LineNum,j]<>Null) do
  189. 186|                                 Begin
  190. 187|                                   HelpLines[LineNum,j]:=Chr(Ord(HelpLines
  191. 188|                                                        [LineNum,j])+128);
  192. 189|                                      Inc(j);
  193. 190|                                 end;
  194. 191|                         If Ord(HelpLines[LineNum,J-1]) in [28..127] then
  195. 192|                         Delete(HelpLines[LineNum],J,2) else
  196. 193|                         Insert(Null+Chr(PageNum),HelpLines[LineNum],j);
  197. 194|                         end;
  198. 195|                  LArrow : If RealLinePos>1 then {Move cursor left 1 char}
  199. 196|                        Begin
  200. 197|                           Dec(linePos);
  201. 198|                           RealLinePos:=Pred(Determine_Actual_Line_Pos
  202. 199|                                            (HelpLines[LineNum],LinePos));
  203. 200|                        end;
  204. 201|                  RArrow : If RealLinePos<=Length(HelpLines[LineNum]) then
  205. 202|                         Begin               {Move cursor right 1 char}
  206. 203|                           Inc(LinePos);
  207. 204|                           If RealLinePos<Length(HelpLines[LineNum]) then
  208. 205|                                   Inc (RealLinePos,
  209. 206|                           1+Ord(HelpLines[LineNum,RealLinePos+1]=Null)*2)
  210. 207|                                 else Inc(realLinePos)
  211. 208|                         end;
  212. 209|                  DnArrow: If LineNum<MaxLinesPerPage then
  213. 210|                       Begin                 {Move down 1 line.}
  214. 211|                          Inc(LineNum);
  215. 212|                          If LinePos<=Length(HelpLines[LineNum]) then
  216. 213|                            RealLinePos:=Pred(Determine_Actual_Line_Pos
  217. 214|                                             (HelpLines[LineNum],LinePos))
  218. 215|                        else
  219. 216|                  Begin
  220. 217|                      RealLinePos:=Succ(Length(HelpLines[LineNum]));
  221. 218|                      LinePos:=RealLinePos-Link_Count(HelpLines[LineNum]);
  222. 219|                  end;
  223. 220|                       end;
  224. 221|            UpArrow: If LineNum>1 then      {Move up 1 line.}
  225. 222|                       Begin
  226. 223|                          Dec(LineNum);
  227. 224|                          If LinePos<=Length(HelpLines[LineNum]) then
  228. 225|                            RealLinePos:=Pred(Determine_Actual_Line_Pos
  229. 226|                                             (HelpLines[LineNum],LinePos))
  230. 227|                          else
  231. 228|                   Begin
  232. 229|                      RealLinePos:=Succ(Length(HelpLines[LineNum]));
  233. 230|                      LinePos:=RealLinePos-Link_Count(HelpLines[LineNum]);
  234. 231|                   end;
  235. 232|                       end;
  236. 233|                  HomeKey: Begin               {Move to 1 char. in line.}
  237. 234|                                 LinePos:=1;
  238. 235|                                 RealLinePos:=LinePos;
  239. 236|                            end;
  240. 237|                  EndKey : Begin                 {Move to end of line.}
  241. 238|                      RealLinePos:=Succ(Length(HelpLines[LineNum]));
  242. 239|                      LinePos:=RealLinePos-Link_Count(HelpLines[LineNum]);
  243. 240|                      end;
  244. 241|                DelKey : If (RealLinePos<=Length(HelpLines[LineNum])) then
  245. 242|                      Begin                 {Delete a character.}
  246. 243|                        If (HelpLines[LineNum,RealLinePos]) in [' '..'}']
  247. 244|                        then Delete(HelpLines[LineNum],RealLinePos,1) else
  248. 245|                        Delete_Linked_Char(HelpLines[LineNum],LinePos);
  249. 246|                        RealLinePos:=Pred(Determine_Actual_Line_Pos
  250. 247|                                            (HelpLines[LineNum],LinePos));
  251. 248|                      end;
  252. 249|                 end else
  253. 250|               Case Ch of
  254. 251|               Return: If LineNum<MaxLinesPerPage then  {Move down 1 line}
  255. 252|                         Begin
  256. 253|                                Inc(LineNum); LinePos:=1; RealLinePos:=1;
  257. 254|                          end;
  258. 255|                   Tab : Begin    {Tab right 10 chars.}
  259. 256|                      If RealLinePos+10<=Length(HelpLines[LineNum])+1 then
  260. 257|                                Inc(RealLinePos,10) else
  261. 258|                      RealLinePos:=Length(HelpLines[LineNum])+1;
  262. 259|                      LinePos:=RealLinePos-Link_Count(HelpLines[LineNum]);
  263. 260|                          end;
  264. 261|                  BkSpc  : If RealLinePos>1 then  {Backspace }
  265. 262|                    Begin
  266. 263|                    If HelpLines[LineNum,RealLinePos-1] in [' '..'}'] then
  267. 264|                     Begin
  268. 265|                              Delete(HelpLines[LineNum],RealLinePos-1,1);
  269. 266|                              Dec(RealLinePos);
  270. 267|                              Dec(LinePos)
  271. 268|                              end else
  272. 269|                     Begin
  273. 270|                         Delete_Linked_Char(HelpLines[LineNum],LinePos-1);
  274. 271|                                  Dec(LinePos);
  275. 272|                                  RealLinePos:=Pred(Determine_Actual_Line_
  276. 273|                                         Pos(HelpLines[LineNum],LinePos));
  277. 274|                     end;
  278. 275|                  end;
  279. 276|        ' '..'}' : If Length(HelpLines[LineNum])<MaxLineWidth then
  280. 277|                      Begin     {Insert a valid Ascii char.}
  281. 278|                         If (Ord(HelpLines[LIneNum,RealLinePos])>127) and
  282. 279|                            (RealLinePos<=Length(HelpLines[Linenum])) then
  283. 280|                            Ch:=Chr(Ord(Ch)+128);
  284. 281|                         Insert(Ch,HelpLines[LineNum],RealLinePos);
  285. 282|                         Inc(RealLinePos);
  286. 283|                         Inc(LinePos); Ch:=#255;
  287. 284|                       end;
  288. 285|              end;
  289. 286|    Until CH in [ESC,PGUp,PgDn]; {ESC=Quit;PGUp=Prev page;PgDn=Next Page.}
  290. 287|    Input_HelpPage:=Ch;
  291. 288|   end; {Input helppage}
  292. 289| {--------------------------------------------------------------------}
  293. 290| FUNCTION Read_Helprec(Var AHelpRec: HelpRecord; RecNum: Integer):Integer;
  294. 291|   Var I : Integer;
  295. 292|   Begin
  296. 293|      FillChar(AHelprec,SizeOf(AHelprec),0); {$I-} {Hyperdata file read }
  297. 294|      If FileSize(HelpFile)<RecNum then exit;    {routine. Includes just }
  298. 295|        Seek(helpfile,RecNum-1);                 {enough error checking  }
  299. 296|        Read(helpfile,AHelpRec);                 {to be considered safe. }
  300. 297|        Read_HelpRec:=IOResult; {$I+}
  301. 298|   end; {Read helprec}
  302. 299| {--------------------------------------------------------------------}
  303. 300| FUNCTION Write_HelpRec(Var AHelpRec: HelpRecord; RecNum:Integer):Integer;
  304. 301|   Begin {$I-}
  305. 302|        Seek(helpfile,RecNum-1);         {Hyperdata file write routine.}
  306. 303|        Write(helpfile,AHelpRec); {$I+}  {This routine contains just  }
  307. 304|        Write_HelpRec:=IOresult;         {enough error checking to be}
  308. 305|   end; {Write helprec}                  {considered safe.}
  309. 306| {--------------------------------------------------------------------}
  310. 307|   FUNCTION Open_HelpFile(FileName: String): Integer;
  311. 308|   Var result: Integer;
  312. 309|   Begin
  313. 310|        Assign(HelpFile,FileName); {$I-}  {Opens hyperdata file specified}
  314. 311|        Reset(HelpFile);                  {as "FileName".  If the file   }
  315. 312|        result:=IOResult;                 {doesnt exist, then it will be }
  316. 313|        If Result=2 then                  {created.                      }
  317. 314|        Begin                             {Error checking is limited, but}
  318. 315|             ReWrite(HelpFile);           {enough to be safe.            }
  319. 316|             Result:=IOResult;
  320. 317|        end;
  321. 318|        Open_HelpFile:=Result;
  322. 319|   end; {open helpfile}
  323. 320| {--------------------------------------------------------------------}
  324. 321|  PROCEDURE Help_Editor(FileName: String);
  325. 322|  Const  HelpMsgs  = 13;
  326. 323|         HelpData  : Array[1..HelpMsgs] of String[17] =
  327. 324|              ( 'Editing Keys: ',          '-------------',
  328. 325|              'F2   : Link (+/-)',       '^Y   : Del EOLine',
  329. 326|              'Bkspc: Del left',         'Del  : Del char',
  330. 327|              Chr(10)+'Movement keys: ', '--------------',
  331. 328|              Chr(24)+Chr(25)+Chr(27)+Chr(26)+', '+Chr(17)+Chr(217)+',',
  332. 329|              'Tab, Home, End',          'PgUp : Prev page',
  333. 330|              'PgDn : Next page',        Chr(10)+'ESC to quit.');
  334. 331| Var I,HelpRecNum: Integer;
  335. 332|      AHelpRec    : HelpRecord;
  336. 333|      Ch          : Char;
  337. 334|      Result      : Integer;
  338. 335|  Begin
  339. 336|       Result:=Open_HelpFile(FileName);     {Open the specified file.}
  340. 337|       If Result=0 then                     {Continue only if no error.}
  341. 338|       Begin
  342. 339|            TextAttr := NormalColor;
  343. 340|            Draw_Box(1,3,80,23,NormalColor,1);
  344. 341|            Draw_Box(2,4,60,22,NormalColor,2);
  345. 342|            Gotoxy(61,4);
  346. 343|            For I:=1 to HelpMsgs do
  347. 344|            Begin
  348. 345|                 Gotoxy(62,WhereY+1); Write(HelpData[i]);
  349. 346|            end;
  350. 347|            HelpRecNum:=1;
  351. 348|            Gotoxy(40-(Length(Header) div 2),3); Writeln(Header);
  352. 349|            Gotoxy(4,2); Writeln('File: ',FileName);
  353. 350|            Repeat
  354. 351|                  Gotoxy(4,4); Writeln(' Reading  ');
  355. 352|                  Result:=Read_HelpRec(AHelpRec,HelpRecNum);
  356. 353|                  Gotoxy(4,4); Writeln('Page: ',HelpRecNum:3);
  357. 354|                   Ch:=Input_HelpPage(3,4,AHelpRec);
  358. 355|                  Result:=Write_HelpRec(AHelpRec,HelpRecNum);
  359. 356|                  Gotoxy(4,4); Writeln(' Writing  ');
  360. 357|                  Case Ch of
  361. 358|                       PgUp : If helpRecNum>1 then Dec(HelpRecNum);
  362. 359|                       PgDn : If HelpRecNum < 255 then Inc(HelpRecNum);
  363. 360|                  end;
  364. 361|            Until Ch=ESC;
  365. 362|   end else  {Report the opening error...}
  366. 363|   Writeln('ERROR: ',Result,' opening ',FileName,'. Unable to continue.');
  367. 364|   {$I-} Close(HelpFile); Result:=IOresult; {$I+}
  368. 365|  end; {Help editor}
  369. 366| {--------------------------------------------------------------------}
  370. 367|  FUNCTION Find_Next_Link( Var X,Y: Integer; EndX,EndY: Integer;
  371. 368|                           Var AHelpRec: HelpRecord): Boolean;
  372. 369|  Var OrigX,OrigY,Col,                {Recursive routine used to find a }
  373. 370|      Row,StartCol,StopCol: Integer;  {hot-link on the page after the   }
  374. 371|  Begin                               {current page position (X,Y).     }
  375. 372|       Find_Next_Link:=False;
  376. 373|       {First, search from current pos to end of page...}
  377. 374|       For Row:=Y to EndY do
  378. 375|       Begin
  379. 376|            If Row<>Y then StartCol:=1 else StartCol:=X;
  380. 377|            If Row<>EndY then StopCol:=Length(AhelpRec.HelpLines[Row])
  381. 378|               else StopCol:=EndX;
  382. 379|            If AhelpRec.HelpLines[Row]<>'' then
  383. 380|            For Col:=StartCol to StopCol do
  384. 381|                If (AHelpRec.HelpLines[Row,Col]=Null) then
  385. 382|                Begin
  386. 383|                     Find_Next_Link:=True;
  387. 384|                     X:=Col; Y:=Row;
  388. 385|                     Exit;  {make a quick getaway!}
  389. 386| end;
  390. 387|       end;
  391. 388|       {ok, search from top of page to the startpos}
  392. 389|       If X+Y>2 then
  393. 390|       Begin
  394. 391|            Col:=1; Row:=1;
  395. 392|            If Find_Next_link(Col,Row,Pred(X),Y,AHelpRec) then
  396. 393|            Begin
  397. 394|                 X:=Col; Y:=Row; Find_Next_Link:=true;
  398. 395|            end
  399. 396|       end;
  400. 397|  end; {find next link}
  401. 398| {--------------------------------------------------------------------}
  402. 399|  FUNCTION Find_Prev_Link( Var X,Y: Integer; EndX,EndY: Integer;
  403. 400|                           Var AHelpRec: HelpRecord): Boolean;
  404. 401|  Var OrigX,OrigY,Col,                 {Recursive routine used to find a }
  405. 402|      Row,StartCol,StopCol: Integer;   {hot-link on the page prev. to the}
  406. 403|  Begin                                {current page pos. (X,Y).         }
  407. 404|       Find_Prev_Link:=False;
  408. 405|       {First, search from current pos to top of page...}
  409. 406|       For Row:=Y downto 1 do
  410. 407|       Begin
  411. 408|            StopCol:=1;
  412. 409|            If Row<>Y then StartCol:=Length(AhelpRec.HelpLines[Row])
  413. 410|               else StartCol:=X;
  414. 411|            If AhelpRec.HelpLines[Row]<>'' then
  415. 412|            For Col:=StartCol downto StopCol do
  416. 413|                If (AHelpRec.HelpLines[Row,Col]=Null) then
  417. 414|                Begin
  418. 415|                     Find_Prev_Link:=True;
  419. 416|                     X:=Col; Y:=Row;
  420. 417|                     Exit;  {make a quick getaway!}
  421. 418|                end;
  422. 419|       end;
  423. 420|       {ok, search from bottom of page to the startpos}
  424. 421|       If X+Y>2 then
  425. 422|       Begin
  426. 423|            Row:=MaxLinesPerPage;
  427. 424|            Col:=Length(AHelpRec.HelpLines[Row]);
  428. 425|            If Find_Prev_link(Col,Row,Succ(X),Y,AHelpRec) then
  429. 426|            Begin
  430. 427|                 X:=Col; Y:=Row; Find_Prev_Link:=true;
  431. 428|            end
  432. 429|       end;
  433. 430|  end; {find prev link}
  434. 431| {--------------------------------------------------------------------}
  435. 432|  PROCEDURE Do_Help(FileName: String; GoPage,HomePage: Word);
  436. 433|  Const XPos = 10;
  437. 434|        YPos = 5;
  438. 435|        Color    : Byte = Black*16+White;   {This is hypertext engine.}
  439. 436|        MaxStackSize = 25;                  {This routine used to read }
  440. 437|                                            {and navigate through data  }
  441. 438|  Type  StackRec = Record                   {file, "FILENAME".}
  442. 439|             Page : Byte;                   {GoPage is starting}
  443. 440|             Row,                           {page to display; HomePage}
  444. 441|             Col  : Integer;                {is used to specify an main }
  445. 442|        end;                                {index (or home) page.  }
  446. 443|  Var   Result  : Integer;
  447. 444|        Stack   : Array[0..MaxStackSize] of StackRec;
  448. 445|        AHelpRec: HelpRecord;
  449. 446|        Ch      : CHar;
  450. 447|        StackLvl: Byte;
  451. 448|        StartCol: Integer;
  452. 449|        Linked,
  453. 450|        Load    : Boolean;
  454. 451|        FUNCTION Pop_Stack: Byte;  {Pop the top page info (Stack) record}
  455. 452|        Begin
  456. 453|             If StackLvl>1 then
  457. 454|             Begin
  458. 455|                  Dec(StackLvl);
  459. 456|                  Load:=True;
  460. 457|             end;
  461. 458|             Pop_Stack:=StackLvl;
  462. 459|        end; {pop stack}
  463. 460|        FUNCTION Push_Stack(PageNum: Byte): Byte;
  464. 461|        Begin                          {Push a page info (stack) record.}
  465. 462|             Inc(StackLvl);
  466. 463|             Stack[StackLvl].Page:=PageNum;
  467. 464|             Stack[StackLvl].Col:=1;
  468. 465|             Stack[StackLvl].Row:=1;
  469. 466|             Push_Stack:=StackLvl;
  470. 467|        end; {push stack}
  471. 468|  Begin
  472. 469|       If GoPage=0 then GoPage:=1;      {Make sure GoPage is valid.}
  473. 470|       Result:=Open_HelpFile(FileName);
  474. 471|       If Result=0 then
  475. 472|       Begin
  476. 473|         Load:=true;
  477. 474|         TextAttr :=Color;
  478. 475|         Draw_Box(Xpos,YPos,XPos+59,YPos+MaxLinesPerPage+2,NormalColor,2);
  479. 476|         FillChar(Stack,SizeOf(Stack),0);
  480. 477|         StackLvl := 0;
  481. 478|         If HomePage in [1..255] then StackLvl:=Push_Stack(HomePage);
  482. 479|         If (GoPage in [1..255]) and (GoPage<>HomePage) then
  483. 480|                                             StackLvl:=Push_Stack(GoPage);
  484. 481|         GotoXY(XPos+29-(Length(Header) div 2),YPos);
  485. 482|         Writeln(Header);
  486. 483|         Repeat
  487. 484|            With Stack[StackLvl] do
  488. 485|                  Begin
  489. 486|                     If Load then  {System needs new hyperdata file page.}
  490. 487|                       Begin
  491. 488|                            Result:=Read_HelpRec(AHelpRec,Page);
  492. 489|                            Show_Help_Page(XPos+1,YPos,AHelpRec);
  493. 490|                            Gotoxy(XPos+51,YPos+MaxLinesPerPage+2);
  494. 491|                            If StackLvl>1 then Write('Esc,PgUp') else
  495. 492|                                                        Write('Esc=Quit');
  496. 493|                            Linked:=Find_Next_Link(Col,Row,80,
  497. 494|                                                MaxLinesPerPage,AHelpRec);
  498. 495|                            Load:=False;
  499. 496|                    end;
  500. 497|                    If Linked then {We have a hot-link to show, so do it.}
  501. 498|                     Begin
  502. 499|                        StartCol := Col;
  503. 500|                        While Ord(AHelprec.HelpLines[Row,StartCol-1])>127
  504. 501|                                                         do Dec(StartCol);
  505. 502|                        Show_HelpLine(XPos+1,YPos+Row,StartCol,Pred(Col),
  506. 503|                                                 AHelpRec.HelpLines[Row]);
  507. 504|                     end;
  508. 505|               Repeat Ch:=Read_KeyBoard until Ch<>Null;
  509. 506|               Show_HelpLine(XPos+1,YPos+Row,0,0,AHelpRec.HelpLines[Row]);
  510. 507|               Case Ch of   {Now handle navigation...}
  511. 508|                            RArrow,
  512. 509|                            Tab    : Begin
  513. 510|                                        Inc(Col);
  514. 511|                                        Linked:=Find_Next_Link(Col,Row,80,
  515. 512|                                                MaxLinesPerPage,AHelpRec);
  516. 513|                                      end;
  517. 514|                            Return : If Linked then
  518. 515|                             Begin
  519. 516|                               Load:=true;
  520. 517|                               If (StackLvl>1) and
  521. 518|                               (Stack[StackLvl-1].Page=
  522. 519|                               Ord(AHelpRec.HelpLines[Row,Col+1])) then
  523. 520|                                      StackLvl:=Pop_Stack else
  524. 521|                               StackLvl:=Push_Stack(Ord(AHelpRec.HelpLines
  525. 522|                                                            [Row,Col+1]));
  526. 523|                            end;
  527. 524|                           LArrow : Begin
  528. 525|                             Dec(Col);
  529. 526|                             Linked:=Find_Prev_Link(Col,Row,1,1,AHelpRec);
  530. 527|                           end;
  531. 528|                        DnArrow: Begin
  532. 529|                         Col:=1;
  533. 530|                         If Row<MaxLinesPerPage then Inc(Row) else Row:=1;
  534. 531|                         Linked:=Find_Next_Link(Col,Row,80,
  535. 532|                                                MaxLinesPerPage,AHelprec);
  536. 533|                        end;
  537. 534|                       UpArrow: Begin
  538. 535|                         If Row>1 then Dec(Row) else Row:=MaxLinesPerPage;
  539. 536|                         If Col<Length(AHelpRec.HelpLines[Row])
  540. 537|                                                            then Inc(Col);
  541. 538|                         Linked:=Find_Prev_Link(Col,Row,1,1,Ahelprec);
  542. 539|                                     end;
  543. 540|                         PgUp   : StackLvl:=Pop_Stack;
  544. 541|                         PgDn   : Begin  {Let programmer set this!} end;
  545. 542|                       end;
  546. 543|                  end;
  547. 544|            Until Ch=ESC;
  548. 545|       end else
  549. 546|   Writeln('ERROR: ',Result,' opening ',FileName,'. Unable to continue.');
  550. 547|   {$I-} Close(HelpFile); result:=IOResult; {$I+}
  551. 548|  end; {do help}
  552. 549| {--------------------------------------------------------------------}
  553. 550|  Begin {No init code required}
  554. 551|  end.